package com.viviet.mobileservices.business.impl;

import java.sql.Timestamp;
import java.util.List;

import org.springframework.security.providers.encoding.PasswordEncoder;

import com.viviet.coreservices.ewallet.EWSConnector;
import com.viviet.mobileservices.business.ICustomerService;
import com.viviet.mobileservices.business.exception.OperationException;
import com.viviet.mobileservices.common.Constants;
import com.viviet.mobileservices.dao.IVMCashflowDAO;
import com.viviet.mobileservices.dao.IVMCustomerDAO;
import com.viviet.mobileservices.dao.IVMQrCodeDAO;
import com.viviet.mobileservices.dao.IVMTransactionDAO;
import com.viviet.mobileservices.dao.entity.VMCustomer;
import com.viviet.mobileservices.dao.entity.VMQrCode;
import com.viviet.mobileservices.dao.entity.VMTransaction;
import com.viviet.mobileservices.domain.info.BalanceInfo;
import com.viviet.mobileservices.domain.info.MessageInfo;
import com.viviet.mobileservices.domain.info.QRCodeInfo;
import com.viviet.mobileservices.domain.info.TransactionInfo;
import com.viviet.mobileservices.domain.model.CustomerModel;
import com.viviet.mobileservices.util.Logit;
import com.viviet.mobileservices.util.Utilities;

/**
 * @description
 * @version TDSBO1.0
 * @CrBy Duong.Van.Sang
 * @CrDate Mar 09, 2012
 * @Copyright HIPT GROUP. All rights reserved.
 */
public class CustomerServiceImpl implements ICustomerService {
	private IVMCashflowDAO cashFlowDAO;
	private IVMCustomerDAO customerDAO;
	private IVMQrCodeDAO qrCodeDAO;
	private IVMTransactionDAO transactionDAO;
	private PasswordEncoder passwordEncoder;
	
	Logit LOG = Logit.getInstance(CustomerServiceImpl.class);

	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#getBalance()
	 */
	@Override
	public BalanceInfo getBalance(CustomerModel model) throws OperationException{
		LOG.debug("Get balance information");
		VMCustomer customer = null;
		
		if (model.isSMSChannel()) {
			customer = new VMCustomer();
			customer.setCustomerId(model.getSender());
		} else {
			customer = Utilities.getWebUserDetails().getUser();
		}
		// verify password
		LOG.debug("Verify password");
		MessageInfo msgInfo = EWSConnector.verifyPassword(customer.getCustomerId(),model.getJ_password());
		
		if (msgInfo.getMsgType() == Constants.OPERATION_SUCCESS) {
			LOG.debug("Password is correct");
			LOG.debug("Get balance");
			MessageInfo msg = EWSConnector.getBalance(customer.getCustomerId());
			
			if (msg.getMsgType() == Constants.OPERATION_SUCCESS) {
				LOG.debug("Get balance succefully");
				BalanceInfo balance = new BalanceInfo();
				balance.setBalance(Long.valueOf(msg.getMsgContent()));
				return balance;
			} else {
				LOG.debug("There is error in getting balance info");
				msgInfo.setMsgCode(Constants.GET_BALANCE_FAILED);
				throw new OperationException(msgInfo);
			}
		} else {
			LOG.debug("Invalid password/username");
			throw new OperationException(msgInfo);
		}
	}

	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#getTransactionsInfo()
	 */
	@Override
	public List<TransactionInfo> getTransactionsInfo(CustomerModel model) {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#transferMoney()
	 */
	@Override
	public MessageInfo transferMoney(CustomerModel model) throws OperationException {
		VMCustomer customer = null;
		
		if (model.isSMSChannel()) {
			customer = new VMCustomer();
			customer.setCustomerId(model.getSender());
		} else {
			customer = Utilities.getWebUserDetails().getUser();
		}
		
		LOG.debug("Transfer money from: "+model.getReceiver() + " to "+ customer.getCustomerId());
		LOG.debug("Verify password");
		MessageInfo msgInfo = EWSConnector.verifyPassword(customer.getCustomerId(),model.getJ_password());
		
		if (msgInfo.getMsgType() == Constants.OPERATION_SUCCESS) {
			LOG.debug("Password correct");
			LOG.debug("Transferring money ....");
			//save transaction information 
			VMTransaction tran = new VMTransaction();
			tran.setAmount(model.getAmount());
			tran.setTransactionType(1);
			tran.setStatus(Constants.TRAN_STATUS_PROCCESSING);
			tran.setSenderId(customer.getCustomerId());
			tran.setReceiverId(model.getReceiver());
			tran.setOrderTime(new Timestamp(System.currentTimeMillis()));
			
			transactionDAO.save(tran);
			
			LOG.debug("Send transaction info to core");
			msgInfo = EWSConnector.transferMoney(customer.getCustomerId(), customer.getCustomerId(), model.getReceiver(), model.getAmount(), model.getComment());
			if (msgInfo.getMsgType() == Constants.OPERATION_SUCCESS){
				LOG.debug("transfer money successfully");
				return msgInfo;
			} else {
				LOG.debug("There is error in transferring money");
				throw new OperationException(msgInfo);
			}
		} else {
			LOG.debug("Invalid password");
			throw new OperationException(msgInfo);
		}
	}
	
	public MessageInfo confirmTransaction(CustomerModel model) {
		
		return null;
	}

	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#changePassword(java.lang.String, java.lang.String)
	 */
	@Override
	public MessageInfo changePassword(String customerId, String oldPassword, String newPassword) {
		LOG.debug("Change password");
		return EWSConnector.changePassword(customerId, oldPassword, newPassword);
	}
	
	@Override
	public MessageInfo registerUser(CustomerModel model) throws OperationException {
		MessageInfo msg = new MessageInfo(Constants.OPERATION_SUCCESS, Constants.REGISTER_SUCCESS, "msg.register_success");
		// validate UseName
		if (model.getUserName() == null || "".equals(model.getUserName().trim())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.username.empty");
		} else if (Utilities.hasSepecialCharacters(model.getUserName())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.username.invalid");
		} else if (loadCustomerByLoginId(model.getUserName()) != null) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.username.existed");
		}
		
		// validate password
		else if (model.getPassword() == null || "".equals(model.getPassword().trim())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.password.empty");
		} else if (Utilities.hasSepecialCharacters(model.getPassword())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.password.invalid");
		} else if (model.getPassword().equals(model.getUserName())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.password.cannot_the_same_with_username");
		}
		
		// validate viviet account
		else if (model.getVivietAcc() == null || "".equals(model.getVivietAcc().trim())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.vivietaccount.empty");
		}
		
		else if (Utilities.hasSepecialCharacters(model.getVivietAcc())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.vivietaccount.invalid");
		}
		else if (Utilities.hasSepecialCharacters(model.getVivietAcc())) {
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgContent("msg.register.error.vivietaccount.invalid");
		} 
		
		if (msg.getMsgType() != Constants.OPERATION_SUCCESS) {
			throw new OperationException(msg);
		}
		
		VMCustomer customer = new VMCustomer();
		customer.setCustomerId(model.getVivietAcc());
		customer.setLoginId(model.getUserName());
		customer.setLoginPass(passwordEncoder.encodePassword(model.getPassword(), null));
		customer.setInputDate(new Timestamp(System.currentTimeMillis()));
		customer.setActiveFlg(1);
		
		try {
			customerDAO.save(customer);
			return msg;
		} catch (RuntimeException ex) {
			LOG.error("Error in register new account", ex);
			msg.setMsgType(Constants.OPERATION_ERROR);
			msg.setMsgCode(Constants.REGISTER_FAILED);
			throw new OperationException(msg);
		}
	}
	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#generateQRCode(CustomerModel model)
	 */
	@Override
	public QRCodeInfo generateQRCode(CustomerModel model) throws OperationException {
		try {
			VMCustomer customer = null;
			
			if (model.isSMSChannel()) {
				customer = customerDAO.findByCustomerId(model.getSender());
			} else {
				customer = Utilities.getWebUserDetails().getUser();
			}
			
			VMQrCode code = new VMQrCode();
			code.setAmount(model.getAmount());
			code.setOwner(customer);
			code.setActiveFlg(1);
			code.setInputDate(new Timestamp(System.currentTimeMillis()));
			
			qrCodeDAO.save(code);
			QRCodeInfo info = new QRCodeInfo();
			info.setId(code.getQrId());
			
			return info;
		} catch (Exception ex) {
			LOG.debug("Error in create QRCode",ex);
			throw new OperationException(new MessageInfo(Constants.OPERATION_ERROR,Constants.QR_CREATE_FAILED,""));
		}
	}
	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#findQRCodeDetailInfo(Integer codeId)
	 */
	@Override
	public QRCodeInfo findQRCodeDetailInfo(String codeId) throws OperationException {
		try {
			VMQrCode code = qrCodeDAO.findById(codeId);
			if (code == null) {
				throw new OperationException(new MessageInfo(Constants.OPERATION_ERROR,Constants.INVALID_REQUEST,""));
			}
			
			QRCodeInfo info = new QRCodeInfo();
			info.setId(code.getQrId());
			info.setReceiver(code.getOwner().getCustomerId());
			info.setAmount(code.getAmount());
			
			return info;
		} catch (RuntimeException ex) {
			MessageInfo msg = new MessageInfo(Constants.OPERATION_ERROR,Constants.QR_GET_FAILED,"");
			throw new OperationException(msg);
		}
	}
	
	/*public String processMessage(CustomerModel model) {
		String sender = model.getSender();
		String smsCommand = model.getCommand();
		model.setSMSChannel(true);
		
		LOG.debug("### SMS SENDER: "+sender);
		LOG.debug("### SMS MESSAGE: "+smsCommand);
		
		String retValue = null;
		if (smsCommand != null && smsCommand.startsWith("MA")) {
			String sms[] = smsCommand.split(" ");
			LOG.debug("### SMS "+sms[1]);
			
			if ("SD".equals(sms[1])) {
				try {
					this.getBalance(model);
				} catch (OperationException ex) {
					
				}
			}
		} else {
			retValue = "";
		}
		
		return retValue;
	}*/

	/* (non-Javadoc)
	 * @see com.viviet.mobileservices.business.ICustomerService#loadCustomerByLoginId(java.lang.String)
	 */
	@Override
	public VMCustomer loadCustomerByLoginId(String loginId) {
		return customerDAO.findByLoginId(loginId);
	}

	/**
	 * @param cashFlowDAO the cashFlowDAO to set
	 */
	public void setCashFlowDAO(IVMCashflowDAO cashFlowDAO) {
		this.cashFlowDAO = cashFlowDAO;
	}

	/**
	 * @param customerDAO the customerDAO to set
	 */
	public void setCustomerDAO(IVMCustomerDAO customerDAO) {
		this.customerDAO = customerDAO;
	}

	/**
	 * @param qrCodeDAO the qrCodeDAO to set
	 */
	public void setQrCodeDAO(IVMQrCodeDAO qrCodeDAO) {
		this.qrCodeDAO = qrCodeDAO;
	}

	/**
	 * @param transactionDAO the transactionDAO to set
	 */
	public void setTransactionDAO(IVMTransactionDAO transactionDAO) {
		this.transactionDAO = transactionDAO;
	}

	/**
	 * @param passwordEncoder the passwordEncoder to set
	 */
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}
}